/* Ty, a programming language interpreter
 * Copyright (C) 2007 Nick Thomas
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "CuTest.h"
#include "data_stack.h"
#include "mem.h"

void ty_make_stack(ty_data_stack *stack)
{
    stack->top = 0;
    stack->size = TY_STACK_INITIAL_SIZE;
    stack->data = ty_malloc(sizeof(ty_obj) * TY_STACK_INITIAL_SIZE);
}

void ty_push(ty_data_stack *stack, ty_obj obj)
{
    if (stack->top == stack->size) {
        stack->size *= 2;
        stack->data = ty_realloc(stack->data, sizeof(ty_obj) * stack->size);
    }

    stack->data[stack->top] = obj;
    stack->top++;
}

int ty_pop(ty_data_stack *stack, ty_obj *obj)
{
    if (stack->top) {
        stack->top--;
        *obj = stack->data[stack->top];
        return 0;
    } else {
        return 1;
    }
}

void ty_test_data_stack(CuTest *tc)
{
    ty_data_stack stack;
    ty_obj obj;

    ty_make_stack(&stack);

    ty_push(&stack, 0xDEAD);
    ty_push(&stack, 0xBEEF);
    ty_pop(&stack, &obj);
    CuAssert(tc, "first ty_pop returns bogus results", obj == 0xBEEF);
    ty_pop(&stack, &obj);
    CuAssert(tc, "second ty_pop returns bogus results", obj == 0xDEAD);
    CuAssert(tc, "third ty_pop does not report underflow",
                ty_pop(&stack, &obj) == 1);

    stack.size = 1;
    ty_push(&stack, 0xABBA);
    ty_push(&stack, 0xFACE);
    CuAssert(tc, "stack size wrong after stack overflow", stack.size == 2);
    CuAssert(tc, "stack top wrong after stack overflow", stack.top == 2);
    CuAssert(tc, "stack contents bogus after stack overflow",
                stack.data[0] == 0xABBA && stack.data[1] == 0xFACE);
}
